#include <GL/gl.h>
#include <algorithm>
#include "include/Model3D.h"

using namespace std;

Model3D::Model3D() 
  : displayList(glGenLists(1)) 
{
}

Model3D::~Model3D() 
{
}

void Model3D::computeCenter()
{
   int nbPoints = shape.getPoints()->size();
   vector<Point3D*>::const_iterator points_ite;
   for(points_ite = shape.getPoints()->begin();
       points_ite != shape.getPoints()->end();
       points_ite++)
   {
      center.setX( center.x() + (*points_ite)->x() );
      center.setY( center.y() + (*points_ite)->y() );
      center.setZ( center.z() + (*points_ite)->z() );
   }
   center.setX( center.x() / nbPoints );
   center.setY( center.y() / nbPoints );
   center.setZ( center.z() / nbPoints );
}

float Model3D::computeMinX() const
{
   float minimum = __FLT_MAX__;

   vector<Point3D*>::const_iterator points_ite;
   for(points_ite = shape.getPoints()->begin();
       points_ite != shape.getPoints()->end();
       points_ite++)
   {
      minimum = min(minimum, (*points_ite)->x());
   }

   return minimum;
}

float Model3D::computeMinY() const
{
   float minimum = __FLT_MAX__;

   vector<Point3D*>::const_iterator points_ite;
   for(points_ite = shape.getPoints()->begin();
       points_ite != shape.getPoints()->end();
       points_ite++)
   {
      minimum = min(minimum, (*points_ite)->y());
   }

   return minimum;
}

float Model3D::computeWidth() const
{
   float minimum = __FLT_MAX__;
   float maximum = __FLT_MIN__;

   vector<Point3D*>::const_iterator points_ite;
   for(points_ite = shape.getPoints()->begin();
       points_ite != shape.getPoints()->end();
       points_ite++)
   {
      minimum = min(minimum, (*points_ite)->x());
      maximum = max(maximum, (*points_ite)->x());
   }

   return maximum-minimum;
}

float Model3D::computeHeight() const
{
   float minimum = __FLT_MAX__;
   float maximum = __FLT_MIN__;

   vector<Point3D*>::const_iterator points_ite;
   for(points_ite = shape.getPoints()->begin();
       points_ite != shape.getPoints()->end();
       points_ite++)
   {
      minimum = min(minimum, (*points_ite)->y());
      maximum = max(maximum, (*points_ite)->y());
   }

   return maximum-minimum;
}

float Model3D::computeSurface() const
{
   return computeWidth() * computeHeight();
}

ostream & operator << (ostream & out, const Model3D & _model3D) 
{ 
   out << *(_model3D.getShape()) << endl;

   out << "indexes :" << endl;
   vector< vector<int> >::const_iterator shapeIndexes_ite;
   vector<int>::const_iterator indexes_ite;
   for(shapeIndexes_ite = _model3D.getShapeIndexes()->begin();
       shapeIndexes_ite != _model3D.getShapeIndexes()->end();
       shapeIndexes_ite++)
   {
      out << "\t";
      for(indexes_ite = shapeIndexes_ite->begin();
          indexes_ite != shapeIndexes_ite->end();
          indexes_ite++)
         out << *indexes_ite << " ";
      out << endl;         
   }

   return out;
}

ostream & operator << (ostream & out, const Shape & _shape) 
{ 
   out << "Points :" << endl;
   vector<Point3D*>::const_iterator points_ite;
   for(points_ite = _shape.getPoints()->begin();
       points_ite != _shape.getPoints()->end();
       points_ite++)
   {
      out << **points_ite;
   }

   return out;
}
